package com.hundsun.cprs.yyt.service.common.service.impl;

import java.util.*;

import com.hundsun.cprs.yyt.response.BaseResponse;
import com.hundsun.cprs.yyt.service.common.dto.*;
import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.enums.EnumBusinessCode;
import com.hundsun.cprs.yyt.common.enums.EnumCommonCode;
import com.hundsun.cprs.yyt.common.exception.ServiceCodeException;
import com.hundsun.cprs.yyt.common.exception.ServiceException;
import com.hundsun.cprs.yyt.service.common.dto.FundOutInRequest;
import com.hundsun.cprs.yyt.service.common.enums.EnumFundBidCode;
import com.hundsun.cprs.yyt.service.fundflow.annotation.FundAnnotation;
import com.hundsun.cprs.yyt.service.rabbit.RoutingKeyConstants;
import com.hundsun.cprs.yyt.util.BeanUtils;
import com.hundsun.cprs.yyt.util.ValueUtils;
import com.hundsun.hps.request.*;
import com.hundsun.hps.result.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.time.DateFormatUtils;
import org.codehaus.jackson.JsonNode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hundsun.cprs.yyt.service.common.service.RemoteTradeFundService;
import com.hundsun.cprs.yyt.util.DateUtil;
import com.hundsun.cprs.yyt.util.StringUtil;
import com.hundsun.hps.enums.converter.FundServiceEnum;
import com.hundsun.hps.request.converter.AccountRequest;
import com.hundsun.hps.request.converter.FundRequest;
import com.hundsun.hps.result.admin.FundBankChannelQueryResponse;
import com.hundsun.hps.result.daily.FundBankKeyResponse;
import com.hundsun.hps.result.dto.FundBankProductDtoResponse;
import com.hundsun.hps.service.admin.AdminService;
import com.hundsun.hps.service.external.FundCommonService;
import com.hundsun.hps.service.webapp.WebAppService;
import com.hundsun.hps.utils.JsonUtils;
import com.hundsun.network.fund.tradegate.result.FundOperateResult;
import com.hundsun.network.fund.tradegate.result.FundSearchResult;
import com.hundsun.network.fund.tradegate.service.FundServiceT2;

/**
 * @author linbo
 * @version 创建时间：2014-5-28 上午10:58:18 统一资金接口，在该接口中调用资金的接口
 */
@Service("remoteTradeFundService")
public class RemoteTradeFundServiceImpl extends BaseService implements RemoteTradeFundService {

	// exchangeId的配置值
	@Value("${hbs.exchangeId:0}")
	private String exchangeId;
	
	@Autowired(required=false)
	public FundServiceT2 fundServiceT2;
	
	@Autowired(required=false)
    private FundCommonService fundCommonService;
	
	@Autowired(required=false)
	private AdminService adminService;

	@Autowired(required=false)
	private WebAppService webAppService;
	@Autowired
    private RabbitTemplate rabbitTemplate;

	// 用资金接口参数处理
	private FundRequest copyTradeFundRequest2FundRequest(TradeFundInfo request) {
		logger.error("内部资金接口参数转换到资金接口参数，参数：" + request.toString());
		FundRequest req = new FundRequest();
		req.setAccountType(request.getAccountType());
		req.setAmount(request.getAmount());
		req.setBankNo(request.getBankNo());
		req.setBizNo(request.getBizNo());
		req.setCdBankCode(request.getCdBankCode());
		req.setCdDate(request.getCdDate());
		req.setCommissionAmount(request.getCommissionAmount());
		req.setDeliveryAmount(request.getDeliveryAmount());
		req.setDepositAmount(request.getDepositAmount());
		req.setFinanceContract(request.getFinanceContract());
		req.setFundAccount(request.getFundAccount());
		req.setFundRequestType(request.getFundRequestType());
		req.setLimitAmount(request.getLimitAmount());
		req.setLoanContract(request.getLoanContract());
		req.setMemo(request.getMemo());
		req.setMoneyType(request.getMoneyType());
		req.setOperator(request.getOperator());
		req.setPayNo(request.getPayNo());
		req.setServiceFeeAmount(request.getServiceFeeAmount());
		req.setServiceFundAccount(request.getServiceFundAccount());
		req.setSettlementfeeAmount(request.getSettlementfeeAmount());// 未成交手续费
		req.setInsuranceFee(request.getInsuredFee());// 保价费
		req.setAuditFee(request.getEvaluateFee());// 送平费
		req.setPremium(request.getInsuranceFee());// 保险费
		req.setTargetNo(request.getTargetNo());
		req.setTradefeeAmount(request.getTradefeeAmount());
		req.setTradeFundAccount(request.getTradeFundAccount());
		req.setTradeNo(request.getTradeNo());
		req.setTransDate(request.getTransDate());
		req.setVarietyType(request.getVarietyType());
		req.setPassword(request.getPayPwd());
		req.setPasswordType(request.getPayPwdType());
		req.setExchangeId(exchangeId);
		return req;
	}

	private TradeFundSearchResult copyFundSearchResult2TradeFundSearchResult(FundSearchResult result) {
		TradeFundSearchResult tResult = new TradeFundSearchResult();
		tResult.setBankAccount(result.getBankAccount());
		tResult.setBankName(result.getBankName());
		tResult.setBankNo(result.getBankNo());
		tResult.setCanGetOutBalance(result.getCanGetOutBalance());
		tResult.setCanUseBalance(result.getCanUseBalance());
		tResult.setCurrentBalance(result.getCurrentBalance());
		tResult.setFrozenBalance(result.getFrozenBalance());
		tResult.setFundAccount(result.getFundAccount());
		tResult.setHolderName(result.getHolderName());
		tResult.setMoneyType(result.getMoneyType() == null ? null : result.getMoneyType().getCode());
		tResult.setStatus(result.getStatus() == null ? null : result.getStatus().getCode());
		tResult.setBankInMoney(result.getBankInMoney());
		tResult.setBankOutMoney(result.getBankOutMoney());
		tResult.setTradeInMoney(result.getTradeInMoney());
		tResult.setTradeOutMoney(result.getTradeOutMoney());
		return tResult;
	}

	/**
	 * 交易商之间的资金划拨
	 * 
	 * @author linbo
	 */
	@Override
	public TradeFundSearchResult searchFundAccountAmount(TradeFundInfo request) {
		if (logger.isDebugEnabled()) {
			logger.debug("调用资金接口RemoteTradeFundServiceImpl.searchFundAccountAmount");
			logger.debug("参数" + request.toString());
		}
		TradeFundSearchResult tsfResult = null;
		FundOperateResult result = null;
		try {
			AccountRequest accountRequest = new AccountRequest();
			accountRequest.setFundAccount(request.getFundAccount());
			accountRequest.setBizNo(request.getBizNo());
			accountRequest.setOperator(request.getOperator());
			accountRequest.setMemo(request.getMemo());
			accountRequest.setExchangeId(exchangeId);
			accountRequest.setSystemCode(request.getBankNo());

			String jsontest = JsonUtils.toJson(accountRequest);
			if(logger.isDebugEnabled()) {
				logger.debug("jsontest:" + jsontest);
			}
			result = fundServiceT2.execute(FundServiceEnum.SEARCH_FUNDACCOUNT_AMOUNT.getCode(), jsontest);
		} catch (Exception e) {
			logger.error("调用资金接口RemoteTradeFundServiceImpl.searchFundAccountAmount失败：", e);
			return tsfResult;
		}
		if (logger.isDebugEnabled()) {
			logger.debug("fundResult:" + result.toString());
		}
		if (StringUtil.isNotEmpty(result.getQueryResult())) {
			FundSearchResult searchResult = (FundSearchResult) JsonUtils.json2Object(result.getQueryResult(),
					FundSearchResult.class);
			tsfResult = copyFundSearchResult2TradeFundSearchResult(searchResult);
		} else {
			logger.error("调用资金接口RemoteTradeFundServiceImpl.searchFundAccountAmount失败,资金对象为空：" + result.getErrorInfo());
		}
		return tsfResult;
	}

	@Override
	public List<FundBankInfo> getAvailableBankList() {
		List<FundBankProductDtoResponse> fundBankProductDtos = fundCommonService.getCanUseBank(exchangeId);
		List<FundBankInfo> bankList = BeanUtils.batchTransform(FundBankInfo.class,fundBankProductDtos);
		return bankList;
	}

	@Override
	public List<FundBankInfo> getMultiAvailableBankList(String type) {
		List<FundMultichannelResponse> fundBankProductDtos = fundCommonService.getCanUseMultichannel(type);
		if (CollectionUtils.isEmpty(fundBankProductDtos)) {
			return Collections.emptyList();
		}
		List<FundBankInfo> bankList = new ArrayList<>(fundBankProductDtos.size());
		for (FundMultichannelResponse channel : fundBankProductDtos) {
			FundBankInfo info = new FundBankInfo();
			info.setBankName(channel.getChannelName());
			info.setBankNo(channel.getBankNo());
			info.setChannelBankNo(channel.getChannelBankNo());
			info.setBankProCode(channel.getBankProCode());
			info.setBankProName(channel.getChannelName());
			info.setStatus(channel.getStatus());
			bankList.add(info);
		}
		return bankList;
	}

	@Override
	public FundMoneyInfo getFundMoneyInfoByFundAccount(String fundAccount) {
		FundMoneyDetailResponse response = fundCommonService.queryFundMoneyDetail(null, null, fundAccount, exchangeId);
		if(response != null){
			return BeanUtils.transfrom(FundMoneyInfo.class, response);
		}
		return null;
	}

	@Override
	public FundCommResponse fundOut(FundOutInRequest request) {
		FundFrontOutInMoney req = new FundFrontOutInMoney();
        //多渠道下出金必填项start
        req.setBankNo(request.getBankNo());
        req.setBankProCode(request.getBankProCode());
        req.setChannelBankNo(request.getChannelBankNo());
        //多渠道下出金必填项end
		req.setFundAccount(request.getFundAccount());
		req.setTransAmount(request.getAmount());
		req.setExchangeId(exchangeId);
		req.setExecuteCode("02");
		//最大长度30位，前8位日期，9-10位是系统编号：01交易系统，02版权授让系统，03衍生品转让系统，04商城系统。日终对账可用
		//TODO:05竞购系统?
		req.setOutBizNo(DateFormatUtils.format(new Date(), "yyyyMMdd05HHmmssSSS"));
		req.setFundOutInMode("0");
		req.setForMainAccount(true);
		req.setMemo(StringUtil.isEmpty(request.getMemo()) ? "提现" : request.getMemo());
		req.setPayPwd(request.getPayPwd());
		req.setReturnUrl(request.getCallbackUrl());
		//微信渠道入参
		req.setOpenId(request.getOpenId());
		req.setCurrentLoginIp(request.getCurrentLoginIp());
		if(request.getUserId() != null){
			req.setUserId(String.valueOf(request.getUserId()));
		}
		try {
            if(logger.isInfoEnabled()){
            	logger.info(ToStringBuilder.reflectionToString(req));
            }
            FundFrontResponse response = fundCommonService.FundBankOutIn(req);
            if(logger.isInfoEnabled()){
            	logger.info("出金返回:" + ToStringBuilder.reflectionToString(response));
            }
            FundCommResponse resp = new FundCommResponse();
            if(!response.getIsSuccess()){
                if("2206".equals(response.getResultCode())){
                    resp.setCode(EnumBusinessCode.BUSSNESS_3016.getErrorNo());
                    resp.setDesc(response.getResultMsg());
                    if(StringUtils.isNotEmpty(response.getReturnUrl())){
                        //资金使用returnUrl字段作为返回附加结果的存储，JSON格式
                        try {
                            JSONObject resultJson = JSONObject.parseObject(response.getReturnUrl());
                            resp.setAttachment(resultJson.getString("postUrl"));
                            //移除URL，剩余未请求内容
                            resultJson.remove("postUrl");
                            resp.setAttachmentDetail(resultJson.toJSONString());
                        } catch (Exception e) {
							//微信无法解析postUrl
							if (StringUtil.isNotBlank(response.getReturnUrl())) {
								resp.setAttachment(response.getReturnUrl());
							}
                        }
                    }
                    return resp;
                }else{
                  //TODO:兼容性修改：避免资金返回错误码为空的问题
                  int resultCode = StringUtils.isNotBlank(response.getResultCode())?Integer.parseInt(response.getResultCode()):EnumBusinessCode.BUSSNESS_3002.getErrorNo();
                  if(resultCode == 2404){
                      //特殊返回代码转换
                      resultCode = EnumBusinessCode.BUSSNESS_3010.getErrorNo();
                  }
                  throw new ServiceCodeException(resultCode,response.getResultMsg());
                }
            }else{
                resp.setCode(EnumCommonCode.COMMON_SUCCESS.getErrorNo());
                resp.setDesc(response.getResultMsg());
            	return resp;
            }
        } catch (ServiceCodeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
	}

	@Override
	public FundCommResponse fundIn(FundOutInRequest request) {
		FundFrontOutInMoney req = new FundFrontOutInMoney();
		//多渠道下入金必填项start
        req.setBankNo(request.getBankNo());
        req.setBankProCode(request.getBankProCode());
        req.setChannelBankNo(request.getChannelBankNo());
        //多渠道下入金必填项end
		req.setFundAccount(request.getFundAccount());
		req.setTransAmount(request.getAmount());
		req.setExchangeId(exchangeId);
		req.setExecuteCode("01");
		//最大长度30位，前8位日期，9-10位是系统编号：01交易系统，02版权授让系统，03衍生品转让系统，04商城系统。日终对账可用
		//TODO:05竞购系统?
		String outBizNo = StringUtils.isNotEmpty(request.getBizNo())?request.getBizNo():DateFormatUtils.format(new Date(), "yyyyMMdd05HHmmssSSS");
		req.setOutBizNo(outBizNo);
		req.setFundOutInMode("0");
		req.setForMainAccount(true);
		req.setMemo(StringUtil.isEmpty(request.getMemo()) ? "充值" : request.getMemo());
		req.setTerminal(ValueUtils.getDefaultValue(request.getBankProTerminal(), "mobile"));//TODO:表明手机端支付
		req.setReturnUrl(request.getCallbackUrl());
		//微信渠道入参
		req.setOpenId(request.getOpenId());
		req.setCurrentLoginIp(request.getCurrentLoginIp());
		if(request.getUserId() != null){
			req.setUserId(String.valueOf(request.getUserId()));
		}
		//双乾支付入金必填
		req.setPayBank(request.getPayBank());
		//附加信息
		req.setDxyzm(request.getValidCode());
		req.setYzmxh(request.getYzmxh());
		//使用协议支付，代收必传
		req.setBankAccount(request.getBankAccount());
		try {
            if(logger.isInfoEnabled()){
            	logger.info(ToStringBuilder.reflectionToString(req));
            }
            FundFrontResponse response = fundCommonService.FundBankOutIn(req);
            if(logger.isInfoEnabled()){
            	logger.info("入金返回:" + ToStringBuilder.reflectionToString(response));
            }
            FundCommResponse resp = new FundCommResponse();
            if(!response.getIsSuccess()){
            	throw new ServiceCodeException(Integer.parseInt(response.getResultCode()),response.getResultMsg());
            }else{
                resp.setCode(EnumCommonCode.COMMON_SUCCESS.getErrorNo());
                resp.setDesc(response.getResultMsg());
                if("2106".equals(response.getResultCode()) && StringUtils.isNotEmpty(response.getReturnUrl())){
                    //资金使用returnUrl字段作为返回附加结果的存储，JSON格式
                    try {
                        JSONObject resultJson = JSONObject.parseObject(response.getReturnUrl());
                        resp.setAttachment(resultJson.getString("postUrl"));
                        //移除URL，剩余未请求内容
                        resultJson.remove("postUrl");
                        resp.setAttachmentDetail(resultJson.toJSONString());
                        resp.setCode(EnumBusinessCode.BUSSNESS_3016.getErrorNo());
                    } catch (Exception e) {
                        //微信无法解析postUrl
						if (StringUtil.isNotBlank(response.getReturnUrl())) {
							resp.setAttachment(response.getReturnUrl());
							resp.setCode(EnumBusinessCode.BUSSNESS_3016.getErrorNo());
						}
                    }
                }
            	//入金消息存入rabbitmq
            	try {
            		//medalRabbitmqDataService.proxyHandle(req);
            	    rabbitTemplate.convertAndSend(RoutingKeyConstants.BID_FUND_OUTIN, req);
            	} catch (ServiceCodeException e) {
            		if(logger.isInfoEnabled()){
            			logger.info("发送入金消息出错，请注意。",e);
            		}
            	} catch (Exception e) {
            		if(logger.isInfoEnabled()){
            			logger.info("发送入金消息出错，请注意。",e);
            		}
            	}
            	return resp;
            }
        } catch (ServiceCodeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
	}


	@Override
	public FundCommResponse open(FundOpenInfo openInfo) {
		AcctransInnerRequest request = new AcctransInnerRequest();
		request.setFundAccount(openInfo.getFundAccount());
		request.setStockAccount(openInfo.getUserId().toString());
		request.setIdKind(openInfo.getCertType());
		request.setIdNo(openInfo.getCertNo());
		request.setBankAccount(openInfo.getBankAccount());
		request.setBankClientNo(openInfo.getBankClientNo());
		request.setBankNo(openInfo.getBankNo());
		request.setCustName(openInfo.getBankAccountName());
		request.setBankProCode(openInfo.getBankProCode());
		request.setChannelBankNo(openInfo.getChannelBankNo());
		request.setCallBackUrl(openInfo.getCallbackUrl());
		request.setExchangeId(exchangeId);
		request.setSubTransCode("010502");
		request.setProcessType(openInfo.getProcessType());
		request.setMode("B");
		request.setDxyzm(openInfo.getVerifiedCode());
		request.setBankBranch(openInfo.getBankBranch());//联交运上海银行必填
		/*通联支付必填*/
		request.setBizNo(openInfo.getBizNo());
		request.setYzmxh(openInfo.getYzmxh());
		request.setDxyzm(openInfo.getDxyzm());
		try {
            if(logger.isInfoEnabled()){
            	logger.info("开户请求:" + JSONObject.toJSONString(request));
            }
            AccountOutResponse response = fundCommonService.open(request);

            if(logger.isInfoEnabled()){
                logger.info("开户返回:" + JSONObject.toJSONString(response));
            }
            FundCommResponse resp = new FundCommResponse();
            resp.setCode(EnumCommonCode.COMMON_SUCCESS.getErrorNo());
            resp.setDesc(EnumCommonCode.COMMON_SUCCESS.getErrorInfo());
            if("0000".equals(response.getEnumFundCode())){
            	//成功
                resp.setSuccess(true);
            }else if("2106".equals(response.getEnumFundCode())){
                //需客户执行开户的下一步业务
                resp.setCode(EnumBusinessCode.BUSSNESS_3016.getErrorNo());
                resp.setSuccess(true);
                if(response.getResultMap() != null){
                    resp.setAttachment(response.getResultMap().get("postUrl"));
                    resp.setAttachmentDetail(JSONObject.toJSONString(response.getResultMap()));
                    //resp.setAttachmentDetail(response.getResultMap().get("ipsRequest"));
                }
            }else if ("2019".equals(response.getEnumFundCode())){
				throw new ServiceCodeException(2019,"账户已绑定");
			}else{
                //其他的业务错误码，以正常的业务异常返回
            	throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1004.getErrorNo(),
            	    standardPrint(response.getEnumFundCode(), response.getEnumFundDesc()));
            }
            return resp;
        } catch (ServiceCodeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
	}

	/**
	 * 资金解绑
	 *
	 * @param closeInfo
	 * @return
	 */
	@Override
	public FundCommResponse close(FundCloseInfo closeInfo) {
		AcctransInnerRequest request = new AcctransInnerRequest();
		request.setFundAccount(closeInfo.getFundAccount());
		request.setBankNo(closeInfo.getBankNo());
		request.setBankProCode(closeInfo.getBankProCode());
		request.setChannelBankNo(closeInfo.getChannelBankNo());
		request.setExchangeId(exchangeId);
		try {
			if(logger.isInfoEnabled()){
				logger.info("解绑请求:" + JSONObject.toJSONString(request));
			}
			AccountOutResponse response = fundCommonService.close(request);
			if(logger.isInfoEnabled()){
				logger.info("解绑返回:" + JSONObject.toJSONString(response));
			}
			FundCommResponse resp = new FundCommResponse();
			resp.setCode(EnumCommonCode.COMMON_SUCCESS.getErrorNo());
			resp.setDesc(EnumCommonCode.COMMON_SUCCESS.getErrorInfo());
			if("0000".equals(response.getEnumFundCode())) {
				//成功
				resp.setSuccess(true);
			} else{
				throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1004.getErrorNo(),
						standardPrint(response.getEnumFundCode(), response.getEnumFundDesc()));
			}
			return resp;
		} catch (ServiceCodeException e) {
			throw e;
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
    public void preOpen(FundOpenInfo openInfo) {
	    AcctransInnerRequest request = new AcctransInnerRequest();
        request.setFundAccount(openInfo.getFundAccount());
        request.setBankProCode(openInfo.getBankProCode());
        request.setBankNo(openInfo.getBankNo());
        request.setBankProCode(openInfo.getBankProCode());
        request.setChannelBankNo(openInfo.getChannelBankNo());
        request.setDxyzm(openInfo.getVerifiedCode());
        
        if(logger.isInfoEnabled()){
            logger.info("签约请求:" + JSONObject.toJSONString(request));
        }
        try {
            AccountOutResponse response = fundCommonService.preOpenAccount(request);
            
            if("0000".equals(response.getEnumFundCode())){
                //成功
            }else{
                throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1004.getErrorNo(),
                    standardPrint(response.getEnumFundCode(), response.getEnumFundDesc()));
            }
        } catch (ServiceCodeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

	@Override
	public List<FundBankClientNo> getBankClientNoList(String accountType, String bankProCode) {
		JSONObject request = new JSONObject();
		request.put("bankProCode", bankProCode);
		request.put("exChangeId", exchangeId);
		//pBankType个人银行，cBankType企业银行
		String keyType = "1".equals(accountType)?"cBankType":"pBankType";
		request.put("keyType", keyType);
		List<FundBankKeyResponse> response = adminService.queryBankKey(request.toJSONString());
		if(CollectionUtils.isNotEmpty(response)){
			List<FundBankClientNo> result = new ArrayList<FundBankClientNo>();
			String keyInfo = response.get(0).getKeyInfo();
			if(StringUtils.isNotBlank(keyInfo)){
				String[] keyInfoArray = keyInfo.split(",");
				for(String item : keyInfoArray){
					String[] itemArray = item.split(":");
					FundBankClientNo itemValue = new FundBankClientNo();
					itemValue.setBankClientNo(itemArray[0]);
					itemValue.setBankName(itemArray[1]);
					result.add(itemValue);
				}
			}
			return result;
		}
		return null;
	}

	@Override
	public boolean checkFundAccountStatus(Long userId) {
		FundOpenStatus fundStatus = getFundAccountStatus(userId);
		if(fundStatus == null)
		    return false;
		return fundStatus.isOpened();
	}
	
    @Override
    public FundOpenStatus getFundAccountStatus(Long userId) {
        String result = fundCommonService.queryStatus(String.valueOf(userId), null, exchangeId);
        if(result == null || result.length() == 0)
            return null;
        FundOpenStatus status = new FundOpenStatus();
        try {
            JSONObject resultJson = JSONObject.parseObject(result);
            status.setStatus(resultJson.getString("status"));
            if(StringUtils.isBlank(resultJson.getString("tax"))){
                status.setSignStatus("0");//给个默认值，兼容下上游业务的判断
            }else{
                status.setSignStatus(resultJson.getString("tax"));
            }
        } catch (Exception e) {
            logger.error("获取开户状态失败",e);
        }
        return status;
    }
	
	@Override
	public String getFundTransDate() {
		String transDate = adminService.getWorkDay(exchangeId);
		return transDate;
	}	
	
	@Override
	public FundBankAccountInfo getBankAccountDetailByFundAccount(String fundAccount) {
		FundBankAccountInfo result = null;
		FundBankAccountResponse response = fundCommonService.bankAccountDetail(null, null, fundAccount, exchangeId);
		if(response != null){
			result = BeanUtils.transfrom(FundBankAccountInfo.class, response);
		}
		return result;
	}
	
	@Override
	public FundBankChannelVerificateInfo sendAndGetBankChannelVerificateCode(FundBankChannelVerificateRequest request) {
		if(logger.isInfoEnabled()){
			logger.info(ToStringBuilder.reflectionToString(request));
		}
		FundBankChannelVerificateInfo response = null;
		//参考资金接口文档1.8
		AcctransInnerRequest req = new AcctransInnerRequest();
		req.setFundAccount(request.getFundAccount());
		req.setChannelBankNo(request.getBankChannelNo());
		//1是入金 0绑卡2解绑
		req.setCodeType(request.getVerifyType());
		req.setAmount(request.getAmount());
		req.setMobile(request.getMobile());
		req.setBankAccount(request.getBankAccount());
		req.setBankBranch(request.getBankClientNo());
		
		try {
            if(logger.isInfoEnabled()){
                logger.info("获取短信校验入参:" + JSONObject.toJSONString(req));
            }
            String result = fundCommonService.getVerificateCode(req);
            if(logger.isInfoEnabled()){
            	logger.info("获取短信校验信息返回:" + result);
            }
            
            if(StringUtils.isNotEmpty(result)){
            	JSONObject jsonResult = JSONObject.parseObject(result);
            	if(jsonResult.getBooleanValue("success")){
            	    response = new FundBankChannelVerificateInfo();
                    response.setBizNo(jsonResult.getString("bizNo"));
                    response.setYzmxh(jsonResult.getString("yzmxh"));
            	}else{
            	  //失败
                  throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1000.getErrorNo(),jsonResult.getString("error"));
            	}
            }else{
            	throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1000.getErrorNo(),"获取短信校验信息失败");
            }
		} catch (ServiceCodeException e) {
		    throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
		return response;
	}

	@Override
	public Map<String, String> getConfigInfoByBankChannel(String bankChannelNo) {
		Map<String,String> result = new HashMap<String, String>();
		JSONObject request = new JSONObject();
		request.put("bankProCode", bankChannelNo);
		request.put("exChangeId", exchangeId);
		//request.put("keyType", bankKey);
		List<FundBankKeyResponse> response = adminService.queryBankKey(request.toJSONString());
		if(CollectionUtils.isNotEmpty(response)){
			for(FundBankKeyResponse temp : response){
				result.put(temp.getKeyType(), temp.getKeyInfo());
			}
		}
		return result;
	}

    @Override
    @FundAnnotation(moduleName="fundBatchExecute",option="通用处理")
    public void batchExecute(FundBatchRequest request) throws ServiceException {
        Assert.notNull(request, "请求参数必填");

        CommonRequest req = request.returnFundBatchTasks();
        if (req == null) {
            return;
        }
        try {
            String requestJson = JSONArray.toJSONString(req);
            if(logger.isDebugEnabled()){
                logger.debug("T2 request :" + requestJson);
            }
            CommonResponse response = fundCommonService.execute(requestJson);
            
            if(logger.isDebugEnabled()){
                logger.debug("T2 response : " + JSONObject.toJSONString(response));
            }
            
            if (!response.isSuccess()) {
                if (response.getResultCode().equals("2001") || 
                    (response.getResultCode().equals("2096") && response.getResultMsg().contains("业务流水已经处理"))) {
                    logger.warn(req.getOutBizNo() + ",该业务流水号资金已处理,交易系统判断为本次执行成功.");
                } else if (response.getResultCode().equals("2002") || response.getResultCode().equals("2068")) {
                    throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1101.getErrorNo(),EnumBusinessCode.BUSINESS_1101.getErrorInfo());
                } else {
                    throw new ServiceCodeException(EnumBusinessCode.BUSSNESS_3003.getErrorNo(),standardPrint(response.getResultCode(),response.getResultMsg()));
                }
            }
        } catch (ServiceCodeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public FundAccountLogInfoResponse getFundAccountLogByPage(FundAccountLogQuery query) {
        FundAccountLogInfoResponse response = null;
        AccountLogQueryResponse innerSearch = new AccountLogQueryResponse();
        innerSearch.setUserId(query.getUserId().toString());
        //innerSearch.setAll(true);//默认为false,按isToday条件决定是否当日查询
        innerSearch.setToday(query.isQueryToday());
        if(query.getStartDate() != null){
            innerSearch.setCreateTimeStart(DateUtil.convertDateToString(DateUtil.DATE_PATTERN, query.getStartDate()));
        }
        if(query.getEndDate() != null){
            innerSearch.setCreateTimeEnd(DateUtil.convertDateToString(DateUtil.DATE_PATTERN, query.getStartDate()));
        }
        innerSearch.setTransCode(query.getTransCode());
        innerSearch.setPageSize(query.getPageSize());
        innerSearch.setCurrentPage(query.getPageNo());
        String requestJson = JSON.toJSONString(innerSearch);
        String responseJson = adminService.queryAccoutLogByCoditionForH5(requestJson);
        if(StringUtils.isNotEmpty(responseJson)){
            /*if(logger.isInfoEnabled()){
                logger.info(responseJson);
            }*/
            response = convertFrom(responseJson);
        }
        return response;
    }
    
    private FundAccountLogInfoResponse convertFrom(String responseJson) {
        FundAccountLogInfoResponse response = null;
        try {
            AccountLogQueryResponse resp = JSON.parseObject(responseJson, AccountLogQueryResponse.class);
            List items = resp.getItems();
            if (items != null) {
                List<FundAccountLogResponse> itemResult = JSON.parseArray(JSON.toJSONString(items), FundAccountLogResponse.class);
                response = new FundAccountLogInfoResponse();
                response.setTotalCount(resp.getTotalItem());
                response.setData(new ArrayList<FundAccountLogInfo>());
                for (FundAccountLogResponse temp : itemResult) {
                    FundAccountLogInfo accountLog = new FundAccountLogInfo();
                    accountLog.setTransCode(temp.getTransCode());
                    accountLog.setTransCodeDesc(temp.transCodeDes());
                    accountLog.setSubTransCode(temp.getSubTransCode());
                    EnumFundBidCode subTransCodeDesc = EnumFundBidCode.indexByValue(temp.getSubTransCode());
                    if(subTransCodeDesc != null) {
                        accountLog.setSubTransCodeDesc(subTransCodeDesc.getAliasInfo());
                    }else{
                        accountLog.setSubTransCodeDesc(temp.transCodeDes());
                    }
                    accountLog.setTransAmount(temp.getTransAmount());
                    accountLog.setPostAmount(temp.getPostAmount());
                    accountLog.setMemo(temp.getMemo());
                    accountLog.setMoneyType(temp.getMoneyType());
                    accountLog.setTransDate(temp.getRealTransDt());
                    response.getData().add(accountLog);
                }
            }
        } catch (Exception e) {
            logger.error("查询资金明细返回解析失败:", e);
        }
        
        return response;
    }
    
    /**
     * 规范资金返回码的输出打印
     */
    private String standardPrint(String code,String message){
        return new StringBuffer("[").append(code).append(",").append(message).append("]").toString();
    }
    

    @Override
    public List<FundBankChannelInfo> getBankChannelInfoByBankProCode(String bankProCode) {
         Assert.hasText(bankProCode, "银行产品代码必填");
         FundBankChannelQueryResponse request = new FundBankChannelQueryResponse();
         request.setBankProCode(bankProCode);
         request.setExchangeId(exchangeId);
         request.setStatus("open");//只查询有效
         String result = webAppService.searchFundBankChannelByCondition(JSON.toJSONString(request));
         List<FundBankChannelInfo>  response = null;
         if(StringUtils.isNotEmpty(result)){
             try {
                List<FundBankChannelQueryResponse> resultList = JSON.parseArray(result, FundBankChannelQueryResponse.class);
                if(CollectionUtils.isNotEmpty(resultList)){
                    response = new ArrayList<FundBankChannelInfo>();
                    for(FundBankChannelQueryResponse item : resultList){
                        FundBankChannelInfo fundBankChannelInfo = new FundBankChannelInfo();
                        fundBankChannelInfo.setBankChannelNo(item.getStandardBankNo());
                        fundBankChannelInfo.setBankChannelName(item.getStandardBankName());
                        response.add(fundBankChannelInfo);
                    }
                }
            } catch (Exception e) {
                 logger.error("查询银行子渠道bankChannelNo 结果[" + result +"]解析异常:",e);
            }
         }
         return response;
    }

	@Override
	public boolean isMultichannel() {
		try {
			return fundCommonService.isMultichannel();
		} catch (Exception e) {
			logger.error("查询资金多渠道状态异常", e);
			throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3017.getErrorNo(), EnumBusinessCode.BUSINESS_3017.getErrorInfo());
		}
	}

	@Override
	public boolean checkMultichannelSign(String fundAccount, String channelBankNo, String executeCode) {
		try {
			Assert.hasText(fundAccount, "资金账号必填");
			Assert.hasText(channelBankNo, "渠道银行编号必填");
			Assert.hasText(executeCode, "出入金类型必填");
			return fundCommonService.checkMultichannelSign(fundAccount, channelBankNo, "0", executeCode);
		} catch (Exception e) {
			logger.error("查询资金多渠道状态异常", e);
			throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3018.getErrorNo(), EnumBusinessCode.BUSINESS_3018.getErrorInfo());
		}
	}

	@Override
	public String getFundMemo(String action, String bankProCode) {
		String result = "";
		try {
			JSONObject request = new JSONObject();
			String keyType = "1".equals(action)?"fundInMemo":"fundOutMemo";
			request.put("keyType", keyType);
			request.put("bankProCode", bankProCode);
			request.put("exChangeId", exchangeId);
			List<FundBankKeyResponse> response = adminService.queryBankKey(request.toJSONString());
			if(CollectionUtils.isNotEmpty(response)){
				FundBankKeyResponse resp = response.get(0);
				if (resp != null)
					result = resp.getKeyInfo();
			}
		} catch (Exception e) {
			logger.error("查询出入金备注信息失败", e);
		}
		return result;
	}

	@Override
	public FundBankOutInApplyResponse getFundApply(BankFundOutInApplyQuery query) {
		FundBankOutInApplyResponse response = null;
		FundOutInApplyQueryResponse innerSearch = new FundOutInApplyQueryResponse();
		innerSearch.setFundAccount(query.getFundAccount());
		innerSearch.setStatus(query.getStatus());
		innerSearch.setOperateType(query.getOperateType());
		if (query.getStartDate() != null) {
			innerSearch.setCreateTimeStart(query.getStartDate());
		}
		if (query.getEndDate() != null) {
			innerSearch.setCreateTimeEnd(query.getEndDate());
		}
		innerSearch.setTotalItem(query.getTotalItem());
		innerSearch.setPageSize(query.getPageSize());
		innerSearch.setCurrentPage(query.getPageNo());
		innerSearch.setExchangeId(exchangeId);
		String result = null;
		try {
			result = webAppService.findAllFundOutInApplyRecordsByStatusIsVerifier(JSON.toJSONString(innerSearch));
			FundOutInApplyQueryResponse fiResponse = null;
			if (StringUtil.isNotEmpty(result)) {
				fiResponse = (FundOutInApplyQueryResponse) JsonUtils.json2Object(result, FundOutInApplyQueryResponse.class);
				if (fiResponse != null) {
					JsonNode nodes = JsonUtils.getObjectMapper().readTree(result);
					String itemsJson = nodes.get("items").toString();
					List<FundOutInApplyResponse> list = JsonUtils.json2ListAppointed(itemsJson, FundOutInApplyResponse.class);
					fiResponse.setItems(list);
					response = copyFundOutInApplyToFundBankOutInApply(fiResponse);
				}
			}
		} catch (Exception e) {
			logger.error("查询资金出入金流水异常:" + e.getMessage());
			return response;
		}
		return response;
	}

	private FundBankOutInApplyResponse copyFundOutInApplyToFundBankOutInApply(FundOutInApplyQueryResponse resp) {
		FundBankOutInApplyResponse response = new FundBankOutInApplyResponse();
		List<FundOutInApplyResponse> list = (List<FundOutInApplyResponse>) resp.getItems();
		response.setTotalCount(resp.getTotalItem());
		List<BankFundOutInApplyInfo> bslist = new ArrayList<>();
		for (FundOutInApplyResponse re : list) {
			BankFundOutInApplyInfo info = new BankFundOutInApplyInfo();
			info.setBankNo(re.getBankNo());
			info.setBankProCode(re.getBankProCode());
			if (re.getGmtCreate() != null) {
				info.setGmtCreate(DateFormatUtils.format(re.getGmtCreate(), "yyyy-MM-dd HH:mm:ss"));
			}
			info.setMemo(re.getMemo());
			info.setOperateType(re.getOperateType());
			info.setStatus(re.getStatus());
			if (re.getVerifierDate() != null) {
				info.setVerifierDate(DateFormatUtils.format(re.getVerifierDate(), "yyyy-MM-dd HH:mm:ss"));
			}
			info.setAmount(re.getAmount());
			bslist.add(info);
		}
		response.setData(bslist);
		return response;
	}

	@Override
	public List<FundBankParamInfo> getBankParamInfoList(String bankProCode, String keyType) {
		JSONObject request = new JSONObject();
		request.put("bankProCode", bankProCode);
		request.put("exChangeId", exchangeId);
		request.put("keyType", keyType);
		List<FundBankKeyResponse> response = adminService.queryBankKey(request.toJSONString());
		if(CollectionUtils.isNotEmpty(response)){
			List<FundBankParamInfo> result = new ArrayList<FundBankParamInfo>();
			String keyInfo = response.get(0).getKeyInfo();
			if(StringUtils.isNotBlank(keyInfo)) {
				//如果是json字符串，则按json解析
				if (isJson(keyInfo)) {
					Map<String,String> maps = (Map)JSON.parse(keyInfo);
					for (Map.Entry<String, String> map : maps.entrySet()){
						FundBankParamInfo itemValue = new FundBankParamInfo();
						itemValue.setParamCode(map.getKey());
						itemValue.setParamMemo(map.getValue());
						result.add(itemValue);
					}
				} else {
					String[] keyInfoArray = keyInfo.split(",");
					for (String item : keyInfoArray) {
						FundBankParamInfo itemValue = new FundBankParamInfo();
						//直接是value值的数据解析
						itemValue.setParamCode(item);
						itemValue.setParamMemo(item);
						result.add(itemValue);
					}
				}
			}else{
				FundBankParamInfo itemValue = new FundBankParamInfo();
				result.add(itemValue);
			}
			return result;
		}
		return null;
	}

	public static boolean isJson(String content) {
		try {
			JSONObject.parseObject(content);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	@Override
	public List<FundPaymentInfoResponse> getFundPaymentConfig(FundPaymentInfoRequest request) {
    	List<FundPaymentInfoResponse> fundPaymentInfoResponseArrayList = null;
    	//入参转换
		FundPaymentConfigRequest fundPaymentConfigRequest = BeanUtils.transfrom(FundPaymentConfigRequest.class,request);
		try{
			//发起资金请求
			List<FundPaymentConfigResponse> fundPaymentConfigResponseList = fundCommonService.getAllPaymentConfig(fundPaymentConfigRequest);
			if (!fundPaymentConfigResponseList.isEmpty()){
				//返回参数转换
				fundPaymentInfoResponseArrayList = BeanUtils.batchTransform(FundPaymentInfoResponse.class,fundPaymentConfigResponseList);
			}
		}catch (Exception e){
			logger.error("查询银行列表信息失败："+ e);
			throw e;
		}
		return fundPaymentInfoResponseArrayList;
	}

	@Override
	public LJBankResponse getBanks(LJBankRequest request) {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getBanks(request.getBankType());
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("获取银行列表失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("获取银行列表失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public LJBankResponse getProveniences() {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getProveniences();
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("获取所有省失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("获取所有省失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public LJBankResponse getCities(LJBankRequest request) {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getCities(request.getProvenienceCode());
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("获取省内所有市失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("获取省内所有市失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public LJBankResponse getAreas(LJBankRequest request) {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getAreas(request.getCityCode());
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("获取市内的区失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("获取市内的区失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public LJBankResponse getBankBranchs(LJBankRequest request) {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getBankBranchs(request.getBankCode(),request.getAreaCode(),request.getProvenienceCode(),request.getCityCode(),request.getKeywords());
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("根据银行、省市区、关键字获取所有联行信息失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("根据银行、省市区、关键字获取所有联行信息失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public LJBankResponse getBankBranch(LJBankRequest request) {
		LJBankResponse LJBankResponse = new LJBankResponse();
		try {
			CommonResponse response  = fundCommonService.getBankBranch(request.getBankBranchCode());
			if (!response.isSuccess()){
				throw new ServiceCodeException(response.getResultMsg());
			}else {
				LJBankResponse.setResultObj(response.getResultObj());
			}
		}catch (ServiceCodeException e){
			logger.error("根据联行号获取联行信息失败：" + e);
			throw e;
		}catch (Exception e){
			logger.error("根据联行号获取联行信息失败：" + e);
			throw e;
		}
		return LJBankResponse;
	}

	@Override
	public Boolean isTradeAble() {
		try {
			return fundCommonService.isTradeAble();
		}catch (Exception e){
			logger.error("从资金获取是否可交易状态失败：" + e);
			throw e;
		}
	}

	@Override
	public List<FundBankAccountDto> getCanUserSignAccount(FundBankAccountRequest request) {
		List<FundBankAccountDto> fundBankAccountDtoList = null;
		//入参转换
		FundSignAccountRequest fundSignAccountRequest = BeanUtils.transfrom(FundSignAccountRequest.class,request);
		try{
			//发起资金请求
			List<FundSignAccountResponse> fundSignAccountResponses = fundCommonService.getCanUserSignAccount(fundSignAccountRequest);
			if (fundSignAccountResponses != null){
				fundBankAccountDtoList = BeanUtils.batchTransform(FundBankAccountDto.class,fundSignAccountResponses);
			}
		}catch (Exception e){
			logger.error("查询可用卡号信息失败："+ e);
			throw new ServiceCodeException(e.getMessage());
		}
		return fundBankAccountDtoList;
	}

	@Override
	public void cancelSignAccount(FundBankAccountRequest request) {
		//入参转换
		FundSignAccountRequest fundSignAccountRequest = BeanUtils.transfrom(FundSignAccountRequest.class,request);
		try{
			//发起资金请求
			CommonResponse commonResponse = fundCommonService.cancelSignAccount(fundSignAccountRequest);
			if (!commonResponse.isSuccess()){
				throw new ServiceCodeException(commonResponse.getResultMsg());
			}
		}catch (ServiceCodeException e){
			throw e;
		}catch (Exception e){
			logger.error("删除卡失败："+ e);
			throw new ServiceCodeException(e.getMessage());
		}
	}
}
